package com.hefan.club.dynamic.service;

import com.alibaba.fastjson.JSONObject;
import com.cat.common.entity.Page;
import com.cat.tiger.service.JedisService;
import com.google.common.collect.Lists;
import com.hefan.club.comment.meta.RedisKeyConstant;
import com.hefan.club.dynamic.bean.DynamicAlbum;
import com.hefan.club.dynamic.bean.Message;
import com.hefan.club.dynamic.bean.MessageConstant;
import com.hefan.club.dynamic.dao.DynamicAlbumDao;
import com.hefan.club.dynamic.dao.DynamicDao;
import com.hefan.club.dynamic.itf.DynamicService;
import com.hefan.club.dynamic.itf.cache.RedisDynamicService;
import com.hefan.common.util.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author wangchao
 * @title: wolf-api
 * @package com.hefan.club.dynamic.service
 * @copyright: Copyright (c) 2017
 * @date 2017-03-14 12:12
 */
@SuppressWarnings("ALL")
@Service("redisDynamicService")
public class RedisDynamicServiceImpl implements RedisDynamicService {

  private Logger logger = LoggerFactory.getLogger(RedisDynamicServiceImpl.class);

  @Resource
  private JedisService jedisService;

  @Resource
  private DynamicService dynamicService;

  @Resource
  private DynamicDao dynamicDao;

  @Resource
  private DynamicAlbumDao dynamicAlbumDao;

  /**
   * 缓存用户点赞数据
   *
   * @param userId
   * @param messageId
   * @return
   * @throws
   * @description （用一句话描述该方法的适用条件执行流程、适用方法、注意事项- 可选）
   * @author wangchao
   * @create 2017-03-14 12:20
   */
  @Override
  public void setPraiseToRedis(String userId, String messageId) {
    try {
      long score = System.currentTimeMillis();
      //增加用户自己的赞数
      Long l = jedisService.zadd(String.format(RedisKeyConstant.PRAISE_SORTED_KEY, messageId), score, userId);
      // 增加动态的赞数
      //jedisService.incrBy(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, messageId), 1);
      logger.info("缓存userId:{}点赞MessageId:{}返回影响行数{}", userId, messageId, l);
    } catch (Exception e) {
      logger.error("缓存用户点赞失败,userId:{},messageId:{}", userId, messageId, e);
    }
  }

  /**
   * 动态发表成功后，缓存明细、更新个人缓存列表和今天发布总数
   *
   * @param message
   * @return a
   * @throws a
   * @description （用一句话描述该方法的适用条件执行流程、适用方法、注意事项- 可选）
   * @author wangchao
   * @create 2017-03-14 12:24
   */
  @SuppressWarnings("unchecked")
  @Override
  public void syncMessage(Message message) {
    try {
      if (message == null) {
        return;
      }
      String key;
      String feedsKey=null;
      // 如果动态类型是视频 & 未转码
      if (Integer.parseInt(message.getMessageType()) == MessageConstant.VIDEOS && !message.getTranscode()) {
        key = String.format(RedisKeyConstant.TRANSCODING_LIST, message.getUserId());
      } else {
        key = String.format(RedisKeyConstant.USER_FEEDS, message.getUserId());
        // 转码完成后，后台直接更新数据库，先判断动态是否转码中,是则从转码中删除，更新到feed中
        String transcodingKey = String.format(RedisKeyConstant.TRANSCODING_LIST, message.getUserId());
        if(jedisService.isExist(transcodingKey)){
          removeTranscodingToFeeds(message);
        }
        //缓存用户自己动态信息，内容按照id降序排列
        feedsKey=String.format(RedisKeyConstant.FEEDS, message.getUserId());
      }
      //logger.info("缓存动态内容={}", JSONObject.toJSONString(message));
      /** 缓存正文，用户feeds列表和频率数点赞数,写入用户feeds列表
       * 动态是否置顶,置顶score 为正，其他的数据score= （10000000-id）*-1
       **/
      double score = message.getMessageId();
      if (StringUtils.isNotBlank(message.getTopStatus()) && message.getTopStatus().equals("1")) {
        score = RedisKeyConstant.BASE_DATA + message.getMessageId();
      }
      // 缓存正文
      jedisService.setexStr(String.format(RedisKeyConstant.SQUARE_HASHSET_KEY2, message.getMessageId()), JSONObject.toJSONString(message), RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
      //缓存用户自己的俱乐部，有置顶功能
      jedisService.zadd(key, score, message.getMessageId());
      //缓存用户动态，无置顶功能
      if(StringUtils.isNotBlank(feedsKey)){
        jedisService.zadd(feedsKey, message.getMessageId(), message.getMessageId());
      }
      //int praise = message.getEwaizan() == null ? 0 : message.getEwaizan() + message.getPraiseCount();
      /*//点赞数
      jedisService.set(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, message.getMessageId()), praise, RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
      //评论数
      jedisService.set(String.format(RedisKeyConstant.FEED_COMMENT_COUNT, message.getMessageId()), message.getCommentCount(), RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
      */
      //缓存相册
      if (Integer.valueOf(message.getMessageType()) == MessageConstant.PICTURE) {
        cacheDynamicAlbum(String.valueOf(message.getMessageId()));
      }

    } catch (Exception e) {
      logger.error("缓存动态内容异常", e);
      e.printStackTrace();
    }
  }

  /**
   * 从缓存删除用户动态，用户动态列表、详细内容、点赞数、评论数、相册
   *
   * @param Message
   * @return
   * @throws
   * @description （用一句话描述该方法的适用条件执行流程、适用方法、注意事项- 可选）
   * @author wangchao
   * @create 2017-03-15 14:28
   */
  @Override
  public void delMessageCache(Message message) throws Exception {
    String key;
    // 如果动态类型是视频 & 未转码
    if (message.getMessageType().equals("3") && !message.getTranscode()) {
      key = String.format(RedisKeyConstant.TRANSCODING_LIST, message.getUserId());
    } else {
      key = String.format(RedisKeyConstant.USER_FEEDS, message.getUserId());
    }

    logger.info("删除缓存动态id={}", message.getMessageId());

    //删除缓存自己俱乐部缓存，有置顶
    jedisService.zrem(key, message.getMessageId());
    //删除详情
    jedisService.del(String.format(RedisKeyConstant.SQUARE_HASHSET_KEY, message.getMessageId()));
    //删除 俱乐部动态缓存
    jedisService.zrem(String.format(RedisKeyConstant.FEEDS, message.getUserId()),message.getMessageId());
    /*//删除点赞数
    jedisService.del(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, message.getMessageId()));
    //删除评论数
    jedisService.del(String.format(RedisKeyConstant.FEED_COMMENT_COUNT, message.getMessageId()));*/
    //删除相册
    delAlbumCache(message.getMessageId());

  }

  public void cacheDynamicAlbum(String id) throws Exception {
    jedisService.del(String.format(RedisKeyConstant.FEED_ALBUM, id));
    // 根据动态ID,查询所有相册
    List<DynamicAlbum> list = dynamicAlbumDao.photoListForMessage(id);
    // 遍历存储redis 中
    for (DynamicAlbum dynamicAlbum : list) {
      jedisService.zadd(String.format(RedisKeyConstant.FEED_ALBUM, id), dynamicAlbum.getId(), dynamicAlbum.getPath());
      jedisService.expire(String.format(RedisKeyConstant.FEED_ALBUM, id), RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
    }
  }

  /**
   * 查询用户今天已发布动态数,先从缓存获取，缓存丢失从数据库获取
   *
   * @param userId
   * @return 返回已发条数
   * @throws Exception
   * @description （用一句话描述该方法的用条件、执行流程、适用方法、注意项 - 可选）
   * @author wangchao
   * @create 2017-03-14 15:42
   */
  @Override
  public int getMessageTotalByUserId(String userId) throws Exception {
    String countKey = String.format(RedisKeyConstant.USER_FEEDS_COUNT, DateUtils.currentDate("yyyyMMdd"), userId);
    String count = jedisService.getStr(countKey);
    logger.info("从缓存获取用户={},key={}数值={}", userId, countKey, count);
    //缓存获取不到，从DB获取并更新redis
    if (StringUtils.isBlank(count)) {
      logger.info("从缓存丢失从数据库获取用户={}", userId);
      String startTime = DateUtils.currentDate("yyyyMMdd 00:00:00");
      String endTime = DateUtils.currentDate("yyyyMMdd 23:59:59");
      int total = dynamicDao.getMessageTotalByUserId(userId, startTime, endTime);
      logger.info("从缓存丢失从数据库获取用户={}，总数={}", userId, total);
      jedisService.setexStr(countKey, String.valueOf(total), RedisKeyConstant.DAY_EXPIRE_TIME);
    }
    return count == null ? 0 : Integer.parseInt(count);
  }

  /**
   * 获取动态详情 :正文，点赞数，评论数
   *
   * @param id
   */
  @Override
  public Message getMessageInfo(String id) {
    try {
      String json = jedisService.getStr(String.format(RedisKeyConstant.SQUARE_HASHSET_KEY2, id));
      //缓存存在
      if (StringUtils.isNotBlank(json)) {
        Message message = JSONObject.parseObject(json, Message.class);
        //修改评论数和点赞数
        /*message.setCommentCount(syncPraiseCount(id));
        message.setPraiseCount(syncCommentCount(id));
        message.setPresentCount(syncPresentCount(id));*/
        return message;
      } else {
        //从db获取
        Message message = dynamicDao.getMessageById(id);
        syncMessage(message);
        return message;
      }
    } catch (Exception e) {
      e.printStackTrace();
      logger.error("获取动态={}内容异常", id, e);
    }
    return null;
  }



  /**
   * 获取动态相册数据
   *
   * @param id
   * @return
   */
  @Override
  public List<Object> getDynamicAlbumCache(long id) {
    try {
      //从缓存中获取动态相册数据
      List<Object> list = jedisService.zrange(String.format(RedisKeyConstant.FEED_ALBUM, id), 0, -1);
      //缓存为空，则从DB获取
      if (CollectionUtils.isEmpty(list)) {
        logger.info("从缓存获取动态={}相册列表为空，DB获取", id);
        cacheDynamicAlbum(String.valueOf(id));
      }
      list = jedisService.zrange(String.format(RedisKeyConstant.FEED_ALBUM, id), 0, -1);
      return list;
    } catch (Exception e) {
      e.printStackTrace();
      logger.error(" 获取动态ID={}相册数据异常", id, e);
      return Lists.newArrayList();
    }
  }

  /**
   * 获取feeds缓存列表
   *
   * @param anchorId 主播ID
   * @param page 分页
   * @param key 缓存可以
   * @param userId 用户ID
   * @return List<Object>
   * @throws
   * @description （用一句话描述该方法的适用条件执行流程、适用方法、注意事项- 可选）
   * @author wangchao
   * @create 2017-03-21 11:03
   */
  @Override
  public List<Object> getFeedsFromCache(String anchorId, Page page, String key, String userId) {
    //获取用户feed
    List<Object> idSet = null;
    //获取用户最新20条动态:idSet
    try {
      int pageNo = page.getPageNo();
      if (pageNo <= 0) {
        pageNo = 1;
      }
      int pageSize = page.getPageSize();
      int start = (pageNo - 1) * pageSize;
      int end = pageNo * pageSize - 1;
      idSet = jedisService.zrevrange(key, start, end);
      // 获取feeds缓存列表为空，则从Db获取
      if (CollectionUtils.isEmpty(idSet)) {
        page = dynamicDao.listMessage(page, anchorId, userId);
        //数据库是否有数据
        if (page != null && !CollectionUtils.isEmpty(page.getResult())) {
          List<Message> list = page.getResult();
          for (Message message : list) {
            idSet.add(message.getMessageId());
            syncMessage(message);
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return CollectionUtils.isEmpty(idSet) ? Lists.newArrayList() : idSet;
  }

  /**
   * 删除相册
   *
   * @param msgId
   */
  @Override
  public void delAlbumCache(Integer msgId) throws Exception {
    try {
      jedisService.del(String.format(RedisKeyConstant.FEED_ALBUM, msgId));
    } catch (Exception e) {
      logger.error("删除相册msgid={}缓存异常", msgId, e);
      jedisService.del(String.format(RedisKeyConstant.FEED_ALBUM, msgId));
    }

  }

  /**
   * 获取主播转码中动态
   *
   * @param authorId
   */
  @Override
  public List<Object> getTranscodingList(String authorId) throws Exception {
    // 如果动态类型是视频 & 未转码
    String key = String.format(RedisKeyConstant.TRANSCODING_LIST, authorId);
    logger.info("用户userId={}从缓存获取转码中动态内容", authorId);
    List<Object> ids = jedisService.zrevrange(key, 0, -1);
    return CollectionUtils.isEmpty(ids) ? Lists.newArrayList() : ids;
  }

  /**
   * 更新用户feed缓存score
   *
   * @param id
   * @param userId
   * @param msgId
   * @param score
   */
  @Override
  public void updateUserFeedsScore(String userId, int msgId, double score) throws Exception {
    Message message = dynamicDao.getMessageById(String.valueOf(msgId));
    if(message==null){
      throw new Exception(String.format("动态id={}，不存在",msgId));
    }
    if(score<=0){
      message.setTopStatus("0");
    }
    syncMessage(message);
    /*String key = String.format(RedisKeyConstant.USER_FEEDS, userId);
    logger.info("用户userId={},动态id={}置顶状态={}", userId, msgId, score > 0 ? "置顶" : "取消置顶");
    //动态置顶
    jedisService.zadd(key, score, msgId);
    jedisService.setexStr(String.format(RedisKeyConstant.SQUARE_HASHSET_KEY2, msgId), JSONObject.toJSONString(message), RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);*/
  }

  /**
   * 转码成功后，更新用户cache
   *
   * @param messageId
   * @param userId
   * @return a
   * @throws Exception
   * @description （用一句话描述该方法的适用条件执行流程、适用方法、注意事项- 可选）
   * @author wangchao
   * @create 2017-03-22 16:06
   */
  @Override
  public void removeTranscodingToFeeds(Message message) throws Exception {
    String key = String.format(RedisKeyConstant.TRANSCODING_LIST, message.getUserId());
    jedisService.zrem(key, message.getMessageId());
    //动态是否置顶
    double score = message.getMessageId() * -1;
    if (StringUtils.isNotBlank(message.getTopStatus()) && message.getTopStatus().equals("1")) {
      score = message.getMessageId();
    }
    jedisService.zadd(key, score, message.getMessageId());
  }

  /**
   * 增加用户每日发送数
   *
   * @param userId
   */
  @Override
  public long incrMessageCount(String userId) throws Exception {
    String countKey = String.format(RedisKeyConstant.USER_FEEDS_COUNT, DateUtils.currentDate("yyyyMMdd"), userId);
    long total = jedisService.incr(countKey);
    jedisService.expire(countKey, RedisKeyConstant.DAY_EXPIRE_TIME);
    return total;
  }


 /* *//**
   * 同步点赞数
   * @param id
   * @param result
   * @return
   * @throws Exception
   *//*
  public Integer syncPraiseCount(String id) throws Exception {
    int count = 0;
    //点赞数
    String praiseCount = jedisService.getStr(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
    if (StringUtils.isBlank(praiseCount)) {
      logger.info("动态id={}，点赞数缓存数据为空从DB获取", id);
      Map<String, Object> map = dynamicDao.getMessageInfoById(Integer.parseInt(id));
      //DB获取数据
      if (!CollectionUtils.isEmpty(map)) {
        Object ewaizan = map.get("ewaizan");
        Object praise = map.get("praise_count");
        //赞数=额外赞数+真实赞数
        logger.info("动态id={}，额外赞数={}，真实点赞数={}", id, ewaizan, praise);
        count = Integer.parseInt(String.valueOf(ewaizan)) + Integer.parseInt(String.valueOf(praise));
        logger.info("动态id={}，点赞数缓存数据为空从DB获取={}", id, count);
        //点赞数
        jedisService.set(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id), count, RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
      }
    }else{
      count=Integer.parseInt(praiseCount);
    }
    return count;
  }*/

  /**
   * 同步评论数
   * @param id
   * @param result
   * @return
   * @throws Exception
   *//*
  public int syncCommentCount(String id) throws Exception {
    logger.info("动态id={}，评论数缓存数据为空从DB获取", id);
    Map<String, Object> map = dynamicDao.getMessageInfoById(Integer.parseInt(id));
    int count = 0;
    //DB获取数据
    if (!CollectionUtils.isEmpty(map)) {
      //评论数
      count = Integer.parseInt(String.valueOf(map.get("comments_count")));
      logger.info("动态id={}，评论数缓存数据为空从DB获取={}", id, count);
      //评论数
      jedisService.set(String.format(RedisKeyConstant.FEED_COMMENT_COUNT, id), map.get("comments_count"), RedisKeyConstant.THREE_MONTH_EXPIRE_TIME);
    }
    return count;
  }*/
  /**
   * 增加评论数、礼物数，
   * @param id
   * @throws Exception
   *//*
  public void incrMessageInfoCount(String id,int type ) throws Exception {

    if (type == 0) {
      // 评论数
      boolean result = jedisService.isExist(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      if (result) {
        jedisService.incr(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      } else {
        syncCommentCount(id);
      }
    } else if (type == 1) {
      //点赞数
      boolean result = jedisService.isExist(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      if (result) {
        jedisService.incr(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      } else {
        syncPraiseCount(id);
      }
    } else if (type == 3) {
      //礼物数
      boolean result = jedisService.isExist(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      if (result) {
        jedisService.incr(String.format(RedisKeyConstant.FEED_PRAISE_COUNT, id));
      } else {
        syncPraiseCount(id);
      }
    }
  }*/
}
